package com.aaa.jvmtest.directmemory;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * 直接内存，ByteBuffer演示
 * 传统读取是从： java方法 -> 本地方法 -> java堆内存(java缓冲区) -> 系统内存(系统缓冲区) -> 磁盘
 * 直接内存是：  java方法 -> 本地方法 -> 系统内存(直接内存)-java内存 -> 磁盘
 * 注意：是在系统内存开辟一块直接内存，java可以直接调用本地方法直接读到(java本身并不具备读取的能力)
 *
 * @author Tu
 * @date 2022/6/15 10:39
 */
public class DirectMemory {

    private static final String FROM = "D:\\音乐.视频\\视频保存\\录屏，学习\\大二(下)\\接口交互,xml属性.mp4";
    private static final String TO = "D:\\音乐.视频\\视频保存\\录屏，学习\\test.mp4";
    private static final int _1MB = 1024 * 1021;

    public static void main(String[] args) {
        //io 用时：689.1778  648.2215  620.4773
        io();
        //directBuffer 用时：414.0219  445.3149  473.0944
        directBuffer();
    }

    /**
     * 传统IO操作
     */
    public static void io() {
        //返回运行的当前时间
        long start = System.nanoTime();
        try (FileInputStream from = new FileInputStream(FROM);
             FileOutputStream to = new FileOutputStream(TO)) {
            //传统读取流固定方式
            byte[] bytes = new byte[_1MB];
            int line;
            while ((line = from.read(bytes)) != -1) {
                //输出  从哪里开始，读取几个字节
                to.write(bytes, 0, line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("io 用时：" + (end - start) / 1000_000.0);
    }

    /**
     * 直接内存读取
     */
    public static void directBuffer() {
        long start = System.nanoTime();
        //直接内存读取
        try (FileChannel from = new FileInputStream(FROM).getChannel();
             FileChannel to = new FileOutputStream(TO).getChannel()) {
            //声明缓冲大小 注意方法不要用错，allocate会报堆内存溢出
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1MB);
            int line;
            while ((line = from.read(byteBuffer)) != -1) {
                //翻转（创建缓冲区）
                byteBuffer.flip();
                //从给定的缓冲区将一个字符序列写入
                to.write(byteBuffer);
                //清除缓冲区
                byteBuffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("directBuffer 用时：" + (end - start) / 1000_000.0);
    }

}
